/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
 *
 */

import path, { resolve } from 'path';

import { expect } from '@jest/globals';
import { HvigorLogger, isWindows } from '@ohos/hvigor';
import execa from 'execa';
import * as fs from 'fs-extra';
import * as fse from 'fs-extra';

import { ExternalNativeOpt } from '../../../src/options/build/build-opt';
import { ProjectBuildProfile } from '../../../src/options/build/project-build-profile';
import { AppJson } from '../../../src/options/configure/app-json-options';
import { ModuleJson } from '../../../src/options/configure/module-json-options';
import { ModuleBuildProfileModifier } from './modifier/module-build-profile-modifier';
import { PackageJsonModifier } from './modifier/package-json-modifier';

import ModuleOptObj = ModuleJson.ModuleOptObj;
import ProjectProfileOpt = ProjectBuildProfile.ProjectProfileOpt;

import { getJson5Obj } from '../../../src/utils/json-util.js';
import { commonConfig } from '../plugins/common-config';

const useNewApplicationTemplate = false;

jest.spyOn(HvigorLogger.prototype, 'errorMessageExit').mockImplementation(
  (message: string, ...args: unknown[]) => {
    throw new Error([message, ...args].toString());
  }
);

jest.spyOn(process, 'exit').mockImplementation(() => {
  return undefined as never;
});

jest.spyOn(HvigorLogger.prototype, 'errorExit').mockImplementation(
  (e: Error, message?: string, ...args: unknown[]) => {
    throw new Error([e.stack, message, ...args].toString());
  }
);

export const DEFAULT_NATIVE_OPTION: { [index: string]: ExternalNativeOpt } = {
  'entry': {
    path: './src/main/cpp/CMakeLists.txt',
    arguments: '-v -DCMAKE_JOB_POOL_COMPILE:STRING=compile ' +
      '-DCMAKE_JOB_POOL_LINK:STRING=link -DCMAKE_JOB_POOLS:STRING=compile=2;link=2',
    abiFilters: [
      'armeabi-v7a',
      'arm64-v8a'
    ],
    cppFlags: ''
  },
  'library': {
    path: './src/main/cpp/CMakeLists.txt',
    arguments: '-v -DCMAKE_JOB_POOL_COMPILE:STRING=compile ' +
      '-DCMAKE_JOB_POOL_LINK:STRING=link -DCMAKE_JOB_POOLS:STRING=compile=2;link=2',
    abiFilters: [
      'armeabi-v7a',
      'arm64-v8a'
    ],
    cppFlags: ''
  }
};

export type hvigorOptions = {
  mode?: string,
  product?: string | string[],
  module?: string | string[],
  log?: string,
  require?: string,
  version?: boolean,
  sync?: boolean,
  tasks: string | string[],
  hotReload?: boolean,
  compileResInc?: string,
  buildMode?: string,
  debuggable?: string,
  daemon?: boolean,
  pageType?: string,
  previewMode?: boolean,
  buildRoot?: string,
  watch?: boolean;
  buildCacheDir?: string,
  hvigorCacheDir?: string,
}

export type initOption = {
  keepTemp?: boolean,
  sign?: boolean,
  prepare?: (temp: string) => Promise<void>,
  cb?: (temp: string) => Promise<void>,
  beforeClean?: (temp: string) => Promise<void>,
  enableNative?: boolean,
  nativeOption?: { [index: string]: ExternalNativeOpt },
  runNpmInstall?: boolean,
  templateVersion?: string
}

const signatureTemplate = [
  {
    'name': 'default',
    'material': {
      storeFile: './sign/myapplication_debug.p12',
      storePassword: '0000001B734C857D79A0AFE684D4F7C9461064D24605328C9AC15302BCB7D9606F8B6D82949497240F684F',
      keyAlias: 'debugKey',
      keyPassword: '0000001B92B7D7143F022695515F8F862090F22016F59D86A642F36AA953ECD76A5DAE6941C04D8FFFF864',
      signAlg: 'SHA256withECDSA',
      profile: './sign/myapplication_debug.p7b',
      certpath: './sign/myapplication_debug.cer'
    }
  },
  {
    'name': 'hos',
    'material': {
      storeFile: './sign-hos/myapplication_debug.p12',
      storePassword: '0000001B2D179B0F5D0EA8CFB3C994FC5182AEF261E80725CECDA0E55D3F312EC1691D321D0C918672CBB5',
      keyAlias: 'debugKey',
      keyPassword: '0000001BAF50B2DA8243ECC645AE9825D734D180624F77D96E7B36EF287539B7BDDD5EF7B1E6049FC9E817',
      signAlg: 'SHA256withECDSA',
      profile: './sign-hos/myapplication_debug.p7b',
      certpath: './sign-hos/myapplication_debug.cer'
    },
    'type': 'HarmonyOS'
  }
];

/**
 * 用临时文件夹初始化一个临时测试工程模板
 *
 * @param model 工程模型类型
 * @param from 要使用的模板测试用例工程
 * @param cb 要执行的测试逻辑方法，接收一个temp参数为临时文件夹的根目录
 * @param options
 * @returns {Promise<void>}
 */
export async function initByProject(
  model: string,
  from: string,
  cb: (temp: string) => Promise<void>,
  options?: initOption
): Promise<void> {
  const initOption = {
    keepTemp: false,
    sign: true,
    ...options
  };
  const templateVersion = process.env.templateVersion || initOption.templateVersion || '';
  await fs.ensureDir(resolve(appRoot(), 'test', 'temp'));
  const temp = await fs.mkdtemp(resolve(appRoot(), 'test', 'temp', 'temp_'));
  try {
    const modelType = model.toLowerCase();
    if (!['fa', 'stage', 'new_stage'].includes(modelType)) {
      fail('Invalid model type. Model type must be one of these: ["FA", "Stage"].');
    }

    await fs.copy(resolve(appRoot(), 'test', 'resources', 'templates', templateVersion, modelType, from), temp);
    if (initOption.prepare) {
      await initOption.prepare(temp);
    }
    const buildProfileObj = getJson5Obj(resolve(temp, 'build-profile.json5'));

    // 添加c++任务执行
    if (initOption.enableNative) {
      const nativeOption = initOption.nativeOption || DEFAULT_NATIVE_OPTION;
      Object.entries(nativeOption).forEach(([moduleName, option]) => {
        new ModuleBuildProfileModifier(temp, moduleName).setNativeOptions(option).outputSync();
      });
    }

    await Promise.all([
      injectSignatureInfo(temp, initOption.sign, buildProfileObj),
      copyLocalProperties(temp),
      runOhpmInstall(temp, buildProfileObj, !!initOption.runNpmInstall)
    ]);
    await cb(temp);
  } finally {
    if (initOption.beforeClean) {
      await initOption.beforeClean(temp);
    }
    if (!initOption.keepTemp) {
      try {
        await fs.remove(temp);
      } catch (e) {
        //
      }
    }
  }
}

export async function initByFAEmptyApp(options: initOption): Promise<void>;
export async function initByFAEmptyApp(cb: (temp: string) => Promise<void>, options?: initOption): Promise<void>;
export async function initByFAEmptyApp(cbOrOpt: ((temp: string) => Promise<void>) | initOption,
  options?: initOption): Promise<void> {
  if (typeof cbOrOpt === 'function') {
    await initByProject('FA', 'Empty_App', cbOrOpt, options);
  } else if (cbOrOpt.cb !== undefined) {
    await initByProject('FA', 'Empty_App', cbOrOpt.cb, cbOrOpt);
  }
}

export async function initByFAJsEmptyApp(options: initOption): Promise<void>;
export async function initByFAJsEmptyApp(cb: (temp: string) => Promise<void>, options?: initOption): Promise<void>;
export async function initByFAJsEmptyApp(cbOrOpt: ((temp: string) => Promise<void>) | initOption,
  options?: initOption): Promise<void> {
  if (typeof cbOrOpt === 'function') {
    await initByProject('FA', 'Js_Empty_App', cbOrOpt, options);
  } else if (cbOrOpt.cb !== undefined) {
    await initByProject('FA', 'Js_Empty_App', cbOrOpt.cb, cbOrOpt);
  }
}

export async function initByFAEmptyService(options: initOption): Promise<void>;
export async function initByFAEmptyService(cb: (temp: string) => Promise<void>, options?: initOption): Promise<void>;
export async function initByFAEmptyService(cbOrOpt: ((temp: string) => Promise<void>) | initOption,
  options?: initOption): Promise<void> {
  if (typeof cbOrOpt === 'function') {
    await initByProject('FA', 'Empty_Service', cbOrOpt, options);
  } else if (cbOrOpt.cb !== undefined) {
    await initByProject('FA', 'Empty_Service', cbOrOpt.cb, cbOrOpt);
  }
}

export async function initByFABigService(options: initOption): Promise<void>;
export async function initByFABigService(cb: (temp: string) => Promise<void>, options?: initOption): Promise<void>;
export async function initByFABigService(cbOrOpt: ((temp: string) => Promise<void>) | initOption,
  options?: initOption): Promise<void> {
  if (typeof cbOrOpt === 'function') {
    await initByProject('FA', 'Big_Service', cbOrOpt, options);
  } else if (cbOrOpt.cb !== undefined) {
    await initByProject('FA', 'Big_Service', cbOrOpt.cb, cbOrOpt);
  }
}

export async function initByStageEmptyApp(options: initOption): Promise<void>;
export async function initByStageEmptyApp(cb: (temp: string) => Promise<void>, options?: initOption): Promise<void>;
export async function initByStageEmptyApp(cbOrOpt: ((temp: string) => Promise<void>) | initOption,
  options?: initOption): Promise<void> {
  let templateProjectBase = 'Stage';
  if (useNewApplicationTemplate) {
    templateProjectBase = 'New_Stage';
  }

  if (typeof cbOrOpt === 'function') {
    await initByProject(templateProjectBase, 'Empty_App', cbOrOpt, options);
  } else if (cbOrOpt.cb !== undefined) {
    await initByProject(templateProjectBase, 'Empty_App', cbOrOpt.cb, cbOrOpt);
  }
}

export async function initByStageEmptyService(options: initOption): Promise<void>;
export async function initByStageEmptyService(cb: (temp: string) => Promise<void>, options?: initOption): Promise<void>;
export async function initByStageEmptyService(cbOrOpt: ((temp: string) => Promise<void>) | initOption,
  options?: initOption): Promise<void> {
  if (typeof cbOrOpt === 'function') {
    await initByProject('Stage', 'Empty_Service', cbOrOpt, options);
  } else if (cbOrOpt.cb !== undefined) {
    await initByProject('Stage', 'Empty_Service', cbOrOpt.cb, cbOrOpt);
  }
}

/**
 * 传入命令和工程根目录，执行hvigor任务
 *
 * @param {string} path 工程根目录
 * @param {string[]} commands 执行命令
 * @param options 额外需要指定的参数
 * @returns {Promise<execa.ExecaChildProcess>}
 */
export function runHvigor(path: string, commands: string[], options?: execa.SyncOptions) {
  try {
    const result = execa.sync('node',
      [require.resolve('@ohos/hvigor/bin/hvigor-simple'), ...commands],
      {
        cwd: path,
        ...options
      });
    if (result.failed) {
      console.error(result.stderr);
    }
    return result;
  } catch (e: any) {
    if (e.stderr) {
      console.error(e.stderr);
    }
    throw e;
  }
}

/**
 * 传入全局命令和工程根目录，执行hvigor任务
 *
 * @param {string[]} commands 执行命令
 * @param options 额外需要指定的参数
 * @returns {Promise<execa.ExecaChildProcess>}
 */
export function runGlobalHvigor(commands: string[], projectRoot?: string, options?: execa.SyncOptions) {
  try {
    const result = execa.sync('node',
      [require.resolve('@ohos/hvigor/src/wrapper/script/hvigor/hvigorw.js'), ...commands],
      {
        cwd:projectRoot,
        ...options
      });
    if (result.failed) {
      console.error(result.stderr);
    }
    return result;
  } catch (e: any) {
    if (e.stderr) {
      console.error(e.stderr);
    }
    throw e;
  }
}

/**
 * 传入命令和工程根目录，执行hvigor任务
 *
 * @param {string} path 工程根目录
 * @param {string[]} commands 执行命令
 * @param options 额外需要指定的参数
 * @param entranceFile 入口文件 '@ohos/hvigor/bin/hvigor', '@ohos/hvigor/bin/hvigor-simple'
 * @returns {Promise<execa.ExecaChildProcess>}
 */
export async function runHvigorAsync(
  path: string, commands: string[], options?: execa.SyncOptions, entranceFile?: string) {
  try {
    const result = await execa('node',
      [require.resolve(entranceFile ? entranceFile : '@ohos/hvigor/bin/hvigor-simple'), ...commands],
      {
        cwd: path,
        ...options
      });
    if (result.failed) {
      console.error(result.stderr);
    }
    return result;
  } catch (e: any) {
    if (e.stderr) {
      console.error(e.stderr);
    }
    throw e;
  }
}

/**
 * 期望执行hvigor失败的情况 返回报错信息
 *
 * @param {string} path 工程根目录
 * @param {string[]} commands 执行命令
 * @param options 额外需要指定的参数
 * @param entranceFile 入口文件 '@ohos/hvigor/bin/hvigor', '@ohos/hvigor/bin/hvigor-simple'
 * @returns {Promise<execa.ExecaChildProcess>}
 */
export async function runHvigorFailAsync(path: string, commands: string[],
  options?: execa.SyncOptions, entranceFile?: string) {
  try {
    const result = await execa('node',
      [require.resolve(entranceFile ? entranceFile : '@ohos/hvigor/bin/hvigor-simple'), ...commands],
      {
        cwd: path,
        ...options
      });
    expect(result.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();
  } catch (e: any) {
    return e;
  }
}

/**
 * 执行hvigor任务，并期望任务失败
 *
 * @param {string} dir 工程目录
 * @param {string[]} commands 执行命令
 * @param {string} error 期望得到的错误信息
 * @returns {Promise<void>}
 */
export function runShouldFail(dir: string, commands: string[], error: string) {
  try {
    runHvigor(dir, commands);
  } catch (e: any) {
    expect(e.stderr).toContain(error);
  }
}

/**
 * 执行hvigor任务，并期望任务失败
 *
 * @param {string} dir 工程目录
 * @param {string[]} commands 执行命令
 * @param {string} error 期望得到的错误信息
 * @returns {Promise<void>}
 */
export function runShouldFailWithMultiErr(dir: string, commands: string[], error: string[]) {
  let result;
  try {
    result = runHvigor(dir, commands, { stderr: 'pipe' });
    expect(result.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();
  } catch (e: any) {
    for (const eElement of error) {
      expect(e?.stderr).toContain(eElement);
    }
  }
}

/**
 * 初始化命令
 *
 * @param {hvigorOptions} options 传入命令参数
 * @returns {string[]} commands 生成命令行指令
 */
export function initExecuteCommand(options: hvigorOptions) {
  const commands: string[] = [];
  const {
    mode,
    product,
    module,
    log,
    require,
    version,
    sync,
    tasks,
    hotReload,
    compileResInc,
    buildMode,
    debuggable,
    daemon,
    pageType,
    previewMode,
    buildRoot,
    watch,
    buildCacheDir,
    hvigorCacheDir
  } = options;
  if (pageType) {
    commands.push('-p');
    commands.push('pageType=page');
  }

  if (previewMode) {
    commands.push('-p');
    commands.push(`previewMode=${previewMode}`);
  }

  if (buildRoot) {
    commands.push('-p');
    commands.push('buildRoot=.preview');
  }

  if (watch) {
    commands.push('--watch');
  }
  if (mode) {
    commands.push('-m');
    commands.push(mode);
  }
  if (product) {
    commands.push('-p');
    if (typeof product === 'string') {
      commands.push(`product=${product}`);
    } else {
      commands.push(`product=${product.join(',')}`);
    }
  }
  if (module) {
    commands.push('-p');
    if (typeof module === 'string') {
      commands.push(`module=${module}`);
    } else {
      commands.push(`module=${module.join(',')}`);
    }
  }
  if (log) {
    commands.push(`-${log}`);
  } else {
    commands.push('-d');
  }
  if (require) {
    commands.push('--require');
    commands.push(require);
  }
  if (version) {
    commands.push('-v');
  }
  if (sync) {
    commands.push('-s');
  }
  if (typeof tasks === 'string') {
    commands.push(tasks);
  } else {
    commands.push(...tasks);
  }
  if (hotReload) {
    commands.push('-p');
    commands.push('hotReload=true');
  }
  if (compileResInc) {
    commands.push('-p');
    commands.push(compileResInc);
  }
  if (buildMode) {
    commands.push('-p');
    commands.push(`buildMode=${buildMode}`);
  }
  if (debuggable) {
    commands.push('-p');
    commands.push(`debuggable=${debuggable}`);
  }
  if (daemon) {
    commands.push('--daemon');
  } else {
    commands.push('--no-daemon');
  }
  if (buildCacheDir) {
    commands.push('--config');
    commands.push(`properties.ohos.buildDir=${buildCacheDir}`);
  }
  if (hvigorCacheDir) {
    commands.push('--config');
    commands.push(`properties.hvigor.cacheDir=${hvigorCacheDir}`);
  }

  commands.push('--stacktrace');
  return commands;
}

/**
 * 返回package的根目录
 *
 * @returns {string} package的根目录
 */
export function appRoot() {
  let dirname = __dirname;
  while (!fs.existsSync(resolve(dirname, 'package.json'))) {
    dirname = resolve(dirname, '..');
  }
  return dirname;
}

/**
 * 注入签名材料和信息
 *
 * @param {string} dest 目标目录
 * @param needSign
 * @param buildProfileObj
 * @returns {Promise<void>}
 */
async function injectSignatureInfo(dest: string, needSign: boolean, buildProfileObj: ProjectProfileOpt) {
  if (!needSign) {
    return;
  }
  buildProfileObj.app.signingConfigs = signatureTemplate;
  await Promise.all([
    fs.copy(resolve(appRoot(), 'test', 'resources', 'common', 'sign'), resolve(dest, 'sign')),
    fs.copy(resolve(appRoot(), 'test', 'resources', 'common', 'sign-hos'), resolve(dest, 'sign-hos')),
    fs.writeJson(resolve(dest, 'build-profile.json5'), buildProfileObj)
  ]);
}

/**
 * 复制local.properties
 *
 * @param {string} dest 目标目录
 * @returns {Promise<void>}
 */
async function copyLocalProperties(dest: string) {
  if (isWindows()) {
    await fs.copy(resolve(appRoot(), 'test', 'resources', 'common', 'WINDOWS'), dest);
  } else {
    await fs.copy(resolve(appRoot(), 'test', 'resources', 'common', 'NONWINDOWS'), dest);
  }
}

/**
 * 执行项目的ohpm install
 *
 * @param {string} path
 * @param buildProfileObj
 * @param runNpmInstall
 * @returns {Promise<execa.ExecaChildProcess>}
 */
async function runOhpmInstall(path: string, buildProfileObj: ProjectProfileOpt, runNpmInstall: boolean): Promise<void> {
  if (runNpmInstall) {
    const srcPaths = [path, ...buildProfileObj.modules.map((unit: ProjectBuildProfile.ModuleBuildOpt) => {
      return resolve(path, unit.srcPath);
    })];
    const ohpmPath = process.env.OHPM_HOME;
    const ohpmInstallCommand = ohpmPath ? `${resolve(ohpmPath, 'bin', 'ohpm')} install` : 'ohpm install';
    await Promise.all(srcPaths.map((srcPath: string) => {
      return execa.command(ohpmInstallCommand, {
        cwd: srcPath
      });
    }));
  }

}

export function updateElementInArrayByUniqueKey<T extends Record<string, unknown>>(array: T[] | undefined, element: T,
  uniqueKey = 'name'): T[] {
  if (array === undefined) {
    return [element];
  }
  for (let i = 0; i < array.length; i++) {
    if (element[uniqueKey] === array[i][uniqueKey]) {
      array[i] = {
        ...array[i],
        ...element
      };
      return array;
    }
  }
  array.push(element);
  return array;
}

export async function addOhosTestDependency(dir: string): Promise<void> {
  new PackageJsonModifier(dir, '').updateDependencies({
    '@ohos/hypium': 'latest'
  }).outputSync();
}

/**
 * openHarmony stage模型 不支持元服务
 *
 * @param projectRoot 工程根目录
 * @param commands 命令行
 * @param moduleName 模块名
 */
export function ohosUnsupportService(projectRoot: string, commands: string[], moduleName: string) {
  const appJson = path.resolve(projectRoot, 'AppScope/app.json5');
  const moduleJson = path.resolve(projectRoot, `${moduleName}/src/main/module.json5`);
  const appJsonOpt: AppJson.AppOptObj = getJson5Obj(appJson);
  const moduleJsonOpt: ModuleOptObj = getJson5Obj(moduleJson);
  if (appJsonOpt.app.bundleType === 'atomicService' || moduleJsonOpt.module.installationFree === true) {
    new ModuleBuildProfileModifier(projectRoot, 'entry').updateTargetRuntimeOS('default', 'OpenHarmony');
    new ModuleBuildProfileModifier(projectRoot, 'feature').updateTargetRuntimeOS('default', 'OpenHarmony');
    new ModuleBuildProfileModifier(projectRoot, 'slibrary').updateTargetRuntimeOS('default', 'OpenHarmony');
    runShouldFail(projectRoot, commands,
      'Atomic service development is not supported in the OpenHarmony stage model.');
  }
}

export function hasCommonElements(arr1: any, arr2: any) {
  return arr1.filter((item: any) => arr2.includes(item)).length > 0;
}

export async function addDependency(modulePath: string, dependencyObj: object) {
  const ohPkgJsonPath = path.resolve(modulePath, 'oh-package.json5');
  const ohPkgJsonObj = getJson5Obj(ohPkgJsonPath);
  Object.assign(ohPkgJsonObj.dependencies, dependencyObj);
  await fse.writeJson(ohPkgJsonPath, ohPkgJsonObj, { spaces: 2 });
  await execa.command(commonConfig.ohpmInstallCommand, {
    cwd: path.resolve(modulePath)
  });
}

export async function addRuntimeOnly(
  modulePath: string, sources: string[], packages: string[]) {
  const buildProfileJsonPath = path.resolve(modulePath, 'build-profile.json5');
  const buildProfileJsonObj = getJson5Obj(buildProfileJsonPath);
  Object.assign(buildProfileJsonObj.buildOptionSet[0].arkOptions, {
    'runtimeOnly': {
      'sources': sources,
      'packages': packages
    }
  });
  await fse.writeJson(buildProfileJsonPath, buildProfileJsonObj, { spaces: 2 });
}

export async function addRouterMap(modulePath: string, routerMapObj: object) {
  await fse.ensureDir(path.resolve(modulePath, 'src/main/resources/base/profile'));
  const routerMapJsonPath = path.resolve(modulePath, 'src/main/resources/base/profile/routerMap.json');
  await fse.ensureFile(routerMapJsonPath);

  const routerMapJsonObj = {
    'routerMap': []
  };

  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  routerMapJsonObj.routerMap.push(routerMapObj);
  await fse.writeJson(routerMapJsonPath, routerMapJsonObj, { spaces: 2 });

  const moduleJsonPath = path.resolve(modulePath, 'src/main/module.json5');
  const moduleJsonObj = getJson5Obj(moduleJsonPath);
  Object.assign(moduleJsonObj.module, { 'routerMap': '$profile:routerMap' });
  await fse.writeJson(moduleJsonPath, moduleJsonObj, { spaces: 2 });
}

/**
 * 复制dir
 * @param src
 * @param dest
 */
export async function copyDir(src: string, dest: string) {
  const entries = await fse.readdir(src, { withFileTypes: true });
  await fse.mkdir(dest, { recursive: true });

  for (const entry of entries) {
    const srcPath = path.join(src, entry.name);
    const destPath = path.join(dest, entry.name);

    if (entry.isDirectory()) {
      await copyDir(srcPath, destPath);
    } else {
      await fse.copyFile(srcPath, destPath);
    }
  }
}

/**
 * har模块新增ability
 * @param harPath
 * @param projectRootPath
 */
export async function addHarAbility(harPath: string, projectRootPath: string): Promise<void> {
  const harModuleJsonPath = path.resolve(harPath, 'src/main/module.json5');
  const moduleJsonObj: ModuleOptObj = getJson5Obj(harModuleJsonPath);
  const harMediaPath = path.resolve(harPath, 'src/main/resources/base/media');
  fse.mkdirSync(harMediaPath);
  await copyDir(path.resolve(projectRootPath, 'entry/src/main/resources/base/media'), harMediaPath);
  fse.copyFileSync(path.resolve(projectRootPath, 'entry/src/main/resources/base/element/color.json'), path.resolve(harPath, 'src/main/resources/base/element/color.json'));
  const harAbility = [{
    'name': 'harAbility',
    'srcEntry': './ets/components/mainpage/MainPage.ets',
    'description': '',
    'icon': '$media:icon',
    'label': '$string:page_show',
    'startWindowIcon': '$media:startIcon',
    'startWindowBackground': '$color:start_window_background'
  }];

  Object.assign(moduleJsonObj.module, { abilities: harAbility });
  fse.writeJSONSync(harModuleJsonPath, moduleJsonObj);
}

/**
 * 为工程设置默认strictMode
 * @param projectRootPath
 */
export function setDefaultStrictMode(projectRootPath: string): void {
  const projectBuildProfilePath = path.resolve(projectRootPath, 'build-profile.json5');
  const projectBuildProfileObj = getJson5Obj(projectBuildProfilePath);
  Object.assign(projectBuildProfileObj.app.products[0], {
    'buildOption': {
      'strictMode': {
        'caseSensitiveCheck': true,
        'useNormalizedOHMUrl': true
      }
    }
  });
  fse.writeJSONSync(projectBuildProfilePath, projectBuildProfileObj);
}

export function isEqual(obj1: any, obj2: any) {
  return JSON.stringify(obj1) === JSON.stringify(obj2);
}
